#include "Neighboring.h"

#include <iostream>
#include <algorithm>

using namespace std;

Neighboring::Neighboring(float ident1)
{
    //ctor
    ident = ident1;
}

Neighboring::~Neighboring()
{
    //dtor
}

void Neighboring::get_assocs(vector<Assoc> &assocs, vector<Match> &matches)
{
    //main loop
    for (int i = 0; i < matches.size(); i++)
    {
        int spacer_len = matches[i].get_spacer_length();
        int virus_len = matches[i].get_virus_length();
        int spacer_loc = matches[i].get_loc_spacer();
        int virus_loc = matches[i].get_loc_virus();
        bool flag = true;
        string matching_sect;
        if (matches[i].get_virus_type() == "genome")
        {
            if (spacer_loc > virus_loc)
            {
                matching_sect = matches[i].get_virus_seq().substr(0, spacer_loc-virus_loc) + matches[i].get_virus_seq().substr(virus_len+(virus_loc-spacer_loc), spacer_len+(virus_loc-spacer_loc));
            }
            else if (virus_loc-spacer_loc+spacer_len > virus_len)
            {
                matching_sect = matches[i].get_virus_seq().substr(0, spacer_len-(virus_len-(virus_loc-spacer_loc))) + matches[i].get_virus_seq().substr(virus_loc-spacer_loc, virus_len-(virus_loc-spacer_loc));
            }
            else
            {
                matching_sect = matches[i].get_virus_seq().substr(virus_loc-spacer_loc, spacer_len);
            }
        }
        else
        {
            if (spacer_loc < virus_loc && virus_loc-spacer_loc+spacer_len < virus_len)
            {
                matching_sect = matches[i].get_virus_seq().substr(virus_loc-spacer_loc, spacer_len);
            }
            else
            {
                flag = false;
            }
        }

        //compare matching sect to spacer
        if (flag == false)
        {
            continue;
        }
        else if (matches[i].get_rev_comp()==false)
        {
            float sim = getSimpleSimilarity(matches[i].get_spacer_seq(), matching_sect);
            if (sim > ident)
            {
                Assoc temp_assoc(matches[i].get_spacer(), matches[i].get_virus(), int(virus_loc-spacer_loc), false, float(sim));
                bool exists = false;
                for (int j = 0; j < assocs.size(); j++)
                {
                    if (assocs[j]==temp_assoc)
                    {
                        exists = true;
                        break;
                    }
                }
                if (exists == false)
                {
                    assocs.push_back(temp_assoc);
                }
            }
        }
        else
        {
            float sim = getSimpleSimilarity(matches[i].get_spacer_seq(), RC(matching_sect));
            if (sim > ident)
            {
                Assoc temp_assoc(matches[i].get_spacer(), matches[i].get_virus(), int(virus_loc-spacer_loc), true, float(sim));
                bool exists = false;
                for (int j = 0; j < assocs.size(); j++)
                {
                    if (assocs[j]==temp_assoc)
                    {
                        exists = true;
                        break;
                    }
                }
                if (exists == false)
                {
                    assocs.push_back(temp_assoc);
                }
            }
        }
    }
}

float Neighboring::getSimpleSimilarity (string seq1, string seq2)
{
    if (seq1.length() != seq2.length())
    {
        cout << "strings of differet sizes" << endl;
        cout << seq1.length() << '\t' << seq2.length() << endl;
        return -1;
    }
    int matches = 0;
    for (int i = 0; i<seq1.size(); i++)
    {
        if (seq1[i]==seq2[i])
        {
            matches++;
        }
    }
    float simil = (float) matches / (float) seq1.length();
    return simil;
}

//makes reverse complment of a sequence
string Neighboring::RC(string seq)
{
    string rc = seq;
    int length = seq.length();
    for (int i = 0; i<length; i++)
    {
        switch (rc[i])
        {
            case 'A':
                rc[i]='T';
                break;
            case 'T':
                rc[i]='A';
                break;
            case 'C':
                rc[i]='G';
                break;
            case 'G':
                rc[i]='C';
                break;
        }
    }
    reverse(rc.begin(), rc.end());
    return rc;
}

